home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#46 (Jul 89)
/
Window Menu Code
/
Window Menu.p
< prev
next >
Wrap
Text File
|
1989-01-19
|
8KB
|
300 lines
(*******************************************************************
Window Menu.p
MDEF for dynamic Window menu demo.
(c) 1988, by Clifford Story & Attic Software
*******************************************************************)
unit WDEF;
(******************************************************************)
interface
(******************************************************************)
uses memtypes, quickdraw, osintf, toolintf, Common;
(******************************************************************)
procedure menudef(message : integer; themenu : MenuHandle;
var menurect : Rect; hitpoint : Point;
var whichitem : integer);
(******************************************************************)
implementation
(******************************************************************)
type
QDrecord = record
randSeed : long;
screenBits : BitMap;
arrow : Cursor;
dkGray : Pattern;
ltGray : Pattern;
gray : Pattern;
black : Pattern;
white : Pattern;
thePort : GrafPtr;
end;
QDpointer = ^QDrecord;
(******************************************************************)
procedure menudraw(themenu : MenuHandle; var menurect : Rect); forward;
procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
hitpoint : Point; var whichitem : integer); forward;
procedure menusize(themenu : MenuHandle); forward;
(******************************************************************)
{$R-}
{$SC+}
(*******************************************************************
menudef
-------
An MDEF is called to do three different things: draw the menu,
hit-test a mouse location, or calculate the menu dimensions.
The “message” parameter determines which service is requested,
so the MDEF simply branches on “message” to specialized routines
that handle the specific functions.
*******************************************************************)
procedure menudef(message : integer; themenu : MenuHandle;
var menurect : Rect; hitpoint : Point;
var whichitem : integer);
begin
case message of
mDrawMsg : menudraw(themenu, menurect);
mChooseMsg : menuchoose(themenu, menurect,
hitpoint, whichitem);
mSizeMsg : menusize(themenu);
end;
end;
(******************************************************************
QDglobals
---------
The QDglobals function returns a pointer to the QuickDraw
globals. This allows procedure definitions and desk accessories
to access the QD globals even though they can't call InitGraf.
******************************************************************)
function QDglobals : QDpointer;
var
thepointer : longpointer;
begin
thepointer := longpointer(currenta5);
thepointer := longpointer(thepointer^);
QDglobals := QDpointer(long(thepointer^)
- sizeof(QDrecord) + sizeof(GrafPtr));
end;
(*******************************************************************
menudraw
--------
The “menudraw” routine draws the menu.
The first item is the “Draw Front Window” command, and the
second is the separating line before the list of window. If
the first item is disabled, then it should be grayed out, by
painting over it with gray.
The remaining items are found in the window list that is kept
by the system. The low-memory global “windowlist” contains a
pointer to the front window. Each window record includes in
turn a pointer to the next window in the list; the last window's
pointer is nil.
Drawing the menu, then, is a simple matter of walking the window
list and drawing each successive window title. But the menu
should include only application windows; for one thing, some DA
windows don't have titles. So the trip through the window list
will skip over windows that aren't “userKind”.
*******************************************************************)
procedure menudraw(themenu: MenuHandle; var menurect: Rect);
var
height : integer;
width : integer;
therect : Rect;
thewindow : WindowPeek;
begin
height := menurect.top + 12;
width := menurect.left + 12;
MoveTo(width, height);
DrawString('Zoom Front Window');
MoveTo(menurect.right - CharWidth('W') - 15, height);
DrawChar(chr(17));
DrawChar('W');
if not BitTst(@themenu^^.enableFlags, 30) then begin
PenPat(QDglobals^.gray);
PenMode(patBic);
with menurect do
SetRect(therect, left, top, right, top + 16);
PaintRect(therect);
PenNormal;
end;
height := height + 16;
MoveTo(menurect.left, menurect.top + 24);
Line(menurect.right - menurect.left, 0);
thewindow := WindowPeek(longpointer(windowlist)^);
while thewindow <> nil do
with thewindow^ do begin
if visible and (windowkind = userKind) then begin
height := height + 16;
MoveTo(width, height);
DrawString(titlehandle^^);
end;
thewindow := nextwindow;
end;
end;
(*******************************************************************
menuchoose
----------
This routine is passed the mouse position, and sets the
“whichitem” parameter to the corresponding menu item.
Since all the menu items are the same height, it's easy to
determine which one the mouse is in - provided it's somewhere
in the menu. If that item is disabled, however, its number
should not be returned; instead the routine should return zero.
Finally, if the mouse is in an active item, and that item is
different from the original value of “whichitem”, then the old
item should be un-highlighted, and the new one highlighted.
*******************************************************************)
procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
hitpoint : Point; var whichitem : integer);
var
theitem : integer;
therect : Rect;
begin
if PtInRect(hitpoint, menurect) then
theitem := 1 + ((hitpoint.v - menurect.top) div 16)
else
theitem := 0;
if not BitTst(@themenu^^.enableFlags, 31 - theitem) then
theitem := 0;
if theitem <> whichitem then begin
therect := menurect;
therect.bottom := therect.top + 16 * theitem;
therect.top := therect.bottom - 16;
InvertRect(therect);
if whichitem > 0 then begin
therect.bottom := menurect.top + 16 * whichitem;
therect.top := therect.bottom - 16;
InvertRect(therect);
end;
whichitem := theitem;
end;
end;
(*******************************************************************
menusize
--------
This routine calculates the dimensions of the menu rectangle.
Similarly to the “menudraw” routine, this routine walks the
window list, and finds the widest item, to base the menu width
on. The menu height is simply the sum of the item heights.
The results are stored in the MenuHandle.
A note: Odd things happened in this routine, with the string
width changing as windows were opened. I can't figure why this
occurred, since Inside Mac says the Menu Manager sets the port
to the Window Manager port. Anyway, the TextFont, TextSize and
TextFace calls cleared up the problem.
*******************************************************************)
procedure menusize(themenu : MenuHandle);
var
thewidth : integer;
theheight : integer;
thewindow : WindowPeek;
newwidth : integer;
begin
TextFont(systemFont);
TextSize(12);
TextFace([]);
theheight := 32;
thewidth := StringWidth('Zoom Front Window')
+ CharWidth('W') + 39;
thewindow := WindowPeek(longpointer(windowlist)^);
while thewindow <> nil do
with thewindow^ do begin
if visible and (windowkind = userKind) then begin
theheight := theheight + 16;
newwidth := StringWidth(titlehandle^^) + 16;
if newwidth > thewidth then
thewidth := newwidth;
end;
thewindow := nextwindow;
end;
themenu^^.menuHeight := theheight;
themenu^^.menuWidth := thewidth;
end;
(******************************************************************)
end.
(******************************************************************)